#include "Skybox.h"

namespace PeanutQuest {

	static GLuint loadTexture(const char *filename) {

		FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
		FIBITMAP *dib(0);
		BYTE* bits(0);
		GLuint gl_texID;
		unsigned int width(0), height(0);

		fif = FreeImage_GetFileType(filename, 0);
		if(fif == FIF_UNKNOWN) {
			fif = FreeImage_GetFIFFromFilename(filename);
			return 0;
		}

		if(FreeImage_FIFSupportsReading(fif))
			dib = FreeImage_Load(fif, filename);
		if(!dib)
			return false;

		dib = FreeImage_ConvertTo24Bits(dib);
		bits = FreeImage_GetBits(dib);
		width = FreeImage_GetWidth(dib);
		height = FreeImage_GetHeight(dib);
		if((bits == 0) || (width == 0) || (height == 0))
			return 0;

		glGenTextures(1, &gl_texID);
		glBindTexture(GL_TEXTURE_2D, gl_texID);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
		glTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, bits);

		FreeImage_Unload(dib);

		return gl_texID;
	}

	Skybox::Skybox(std::string id) : cg::Entity(id) {
	}
	Skybox::~Skybox() {
	}

	inline
	void Skybox::makeTexture() {
		_top = loadTexture("../../img/skybox/top.jpg");
		_bottom = loadTexture("../../img/skybox/bottom.jpg");
		_left = loadTexture("../../img/skybox/left.jpg");
		_right = loadTexture("../../img/skybox/right.jpg");
		_front = loadTexture("../../img/skybox/front.jpg");
		_back = loadTexture("../../img/skybox/back.jpg");
	}

	void Skybox::init() {
		_low = -50.5f;
		_high = 50.5f;
		makeTexture();
	}

	void Skybox::draw() {

		glPushMatrix();
		glLoadIdentity();
		glColor4f(1,1,1,1);
		glEnable(GL_TEXTURE_2D);

		// Render the front quad
		glBindTexture(GL_TEXTURE_2D, _front);
		glBegin(GL_QUADS);
			glTexCoord2f(0, 0); glVertex3f(  _high, _low, _low );
			glTexCoord2f(1, 0); glVertex3f( _low, _low, _low );
			glTexCoord2f(1, 1); glVertex3f( _low,  _high, _low );
			glTexCoord2f(0, 1); glVertex3f(  _high,  _high, _low );
		glEnd();

		// Render the left quad
		glBindTexture(GL_TEXTURE_2D, _left);
		glBegin(GL_QUADS);
			glTexCoord2f(0, 0); glVertex3f(  _high, _low,  _high );
			glTexCoord2f(1, 0); glVertex3f(  _high, _low, _low );
			glTexCoord2f(1, 1); glVertex3f(  _high,  _high, _low );
			glTexCoord2f(0, 1); glVertex3f(  _high,  _high,  _high );
		glEnd();

		// Render the back quad
		glBindTexture(GL_TEXTURE_2D, _back);
		glBegin(GL_QUADS);
			glTexCoord2f(0, 0); glVertex3f( _low, _low,  _high );
			glTexCoord2f(1, 0); glVertex3f(  _high, _low,  _high );
			glTexCoord2f(1, 1); glVertex3f(  _high,  _high,  _high );
			glTexCoord2f(0, 1); glVertex3f( _low,  _high,  _high );
 
		glEnd();
 
		// Render the right quad
		glBindTexture(GL_TEXTURE_2D, _right);
		glBegin(GL_QUADS);
			glTexCoord2f(0, 0); glVertex3f( _low, _low, _low );
			glTexCoord2f(1, 0); glVertex3f( _low, _low,  _high );
			glTexCoord2f(1, 1); glVertex3f( _low,  _high,  _high );
			glTexCoord2f(0, 1); glVertex3f( _low,  _high, _low );
		glEnd();
 
		// Render the top quad
		glBindTexture(GL_TEXTURE_2D, _top);
		glBegin(GL_QUADS);
			glTexCoord2f(0, 1); glVertex3f( _low,  _high, _low );
			glTexCoord2f(0, 0); glVertex3f( _low,  _high,  _high );
			glTexCoord2f(1, 0); glVertex3f(  _high,  _high,  _high );
			glTexCoord2f(1, 1); glVertex3f(  _high,  _high, _low );
		glEnd();
 
		// Render the bottom quad
		glBindTexture(GL_TEXTURE_2D, _bottom);
		glBegin(GL_QUADS);
			glTexCoord2f(0, 0); glVertex3f( _low, _low, _low );
			glTexCoord2f(0, 1); glVertex3f( _low, _low,  _high );
			glTexCoord2f(1, 1); glVertex3f(  _high, _low,  _high );
			glTexCoord2f(1, 0); glVertex3f(  _high, _low, _low );
		glEnd();

		glDisable(GL_TEXTURE_2D);
		glPopAttrib();
		glPopMatrix();
	
	}

}